﻿using HZH_Controls.Controls;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Client.样式类;
using RRQMSocket;
using Client.工具类;
using RRQMSocket.FileTransfer;
using RRQMCore.ByteManager;
using System.Collections;
using Client.Json;
using System.IO;
using MaterialSkin;
using System.Reflection;
using System.Resources;
using WMPLib;
using Client.Properties;
namespace Client.窗体
{
    public partial class Main : Form
    {
        WMPLib.WindowsMediaPlayer wplayer = new WMPLib.WindowsMediaPlayer();
        const string cfg = "cfg.ini";
        string IP, P1, P2, Token;
        Config cf;
        string path = "";
        string uid = "未知";
        string currentMusic = "";
        string[] currentTitle = new  string[5];
        List<string[]> musicList;
        List<string[]> playList=new List<string[]>();
        private FileClient fileClient;
        SimpleTcpClient tcpClient = new SimpleTcpClient();

        public Main()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;
        }

        private void Main_Load(object sender, EventArgs e)
        {
            
            loadCfg();
           // loadDemo();
            ConnectMsgService();
            ConnectFileService();
            wplayer.PlayStateChange += wplayerPlayStateChange;
        }

		private void wplayerPlayStateChange(int NewState)
		{
            
            switch (NewState)
			{
                case 0://未知状态
                    ucBtnImg1.Image = Resources.play;
                    break;
                case 1://播放停止

                    
                    //ucBtnImg1.Image = Resources.play;
                    break;
                case 2://播放暂停
                    ucBtnImg1.Image = Resources.play;
                    break;
                case 3://正在播放
                    ucBtnImg1.Image = Resources.pause;

                    MPlayer mPlayer = new MPlayer(wplayer.URL);
                    materialLabel1.Text = mPlayer.getTitle();
                    materialLabel2.Text = mPlayer.getArtists();
                    materialLabel3.Text = mPlayer.getAlbum();
                    break;
                default:
					break;
			}
		}

		void loadCfg()
        {
            if (!Directory.Exists(Application.StartupPath + @"\MusicCache"))
            {
                Directory.CreateDirectory(Application.StartupPath + @"\MusicCache");
            }
            path = Application.StartupPath + @"\MusicCache";
            cf = new Config(cfg);
            IP = cf.get("IP");
            P1 = cf.get("P1");
            P2 = cf.get("P2");
            Token = cf.get("Token");
        }

        private void ConnectFileService()
        {
            if (fileClient == null)
            {
                fileClient = new FileClient();
                fileClient.TransferFileError += FileClient_TransferFileError;
                fileClient.BeforeFileTransfer += FileClient_BeforeFileTransfer; ;
                fileClient.FinishedFileTransfer += FileClient_FinishedFileTransfer; ;
                fileClient.DisconnectedService += FileClient_DisConnectedService;
                fileClient.ConnectedService += FileClient_ConnectedService;
                fileClient.Received += FileClient_Received;
            }

            try
            {
                var config = new FileClientConfig();
                // config.Logger = new MsgLog(Log);
                config.RemoteIPHost = new IPHost(IP + ":" + P2);//服务器地址
                config.VerifyToken = Token;//连接验证令箭
                config.BufferLength = 64 * 1024;//缓存池，该值太小会影响接收效率
                config.PacketSize = 64 * 1024;//包尺寸，当网络比较差时，应该设置小点，最大值不能超过10Mb
                config.DataHandlingAdapter = new FixedHeaderDataHandlingAdapter();//此处允许设置数据处理适配器，但是只能设置固定包头。
                config.ReceiveDirectory = "Received";//此处可以设置默认下载文件目录，但是最终路径受UrlFileInfo.SaveFullPath决定。
                config.Timeout = 10 * 1000;//设置默认单次请求最大等待时间。
                fileClient.Setup(config);
                fileClient.Connect();
            }
            catch (Exception ex)
            {
                if (fileClient != null && fileClient.Online)
                {
                    fileClient.Dispose();
                }

                fileClient = null;
                Log(ex.Message);
            }
        }
        private void FileClient_Received(object sender, short? procotol, ByteBlock byteBlock)
        {
            Log($"收到：协议={procotol}，信息={Encoding.UTF8.GetString(byteBlock.Buffer, 2, (int)byteBlock.Length - 2)}");
        }


        private void FileClient_ConnectedService(object sender, MesEventArgs e)
        {
           Log( "连接文件服务器成功");
        }

        private void FileClient_DisConnectedService(object sender, MesEventArgs e)
        {
            Log("与服务器断开连接");
        }

        private void FileClient_FinishedFileTransfer(object sender, TransferFileMessageArgs e)
        {
            FileClient fileClient = sender as FileClient;//客户端中事件的sender实例均为FileClient
            UrlFileInfo fileInfo = e.UrlFileInfo;//通过事件参数值，可获得完成的文件信息
            if (e.TransferType == TransferType.Download)
            {
                Log(string.Format("文件：{0}下载完成", e.UrlFileInfo.FileName));

                Log("下载完成");
                //label9.Text = "已缓存";

                pictureBox1.Image = Client.Properties.Resources.已缓存;
                // string title = listBox1.SelectedItem.ToString().Split('|')[3] + "." + listBox1.SelectedItem.ToString().Split('|')[4];

                wplayer.URL = path + "\\" + currentMusic;

            }
            else
            {
                Log(string.Format("文件：{0}上传完成", e.UrlFileInfo.FileName));
            }
        }

        private void FileClient_BeforeFileTransfer(object sender, FileOperationEventArgs e)
        {
            if (e.TransferType == TransferType.Download)
            {
                string Path = Application.StartupPath + @"\MusicCache\"+currentMusic;
                e.UrlFileInfo.SaveFullPath = Path;
            }
        }

        private void FileClient_TransferFileError(object sender, TransferFileMessageArgs e)
        {
            Log($"传输类型：{e.TransferType}，信息：{e.Message}");
        }
		void Log(string msg)
        {
            this.Text +=",," +msg;
        }

		private void ConnectMsgService()
		{
            tcpClient.ConnectedService += (object sender, MesEventArgs e) =>
            {
                //成功连接到服务器
                //sender对象为SimpleTcpClient类型
                SimpleTcpClient client = (SimpleTcpClient)sender;

                this.Text = "连接服务器成功";


            };

            tcpClient.DisconnectedService += (object sender, MesEventArgs e) =>
            {
                //从服务器断开连接，当连接不成功时不会触发。
                //sender对象为SimpleTcpClient类型
                SimpleTcpClient client = (SimpleTcpClient)sender;
                this.Text = "服务器断开";

                //label4.Text = "你当前的UID:未知";
                uid = "未知";
            };

            tcpClient.Received += (ByteBlock byteBlock, object arg2) =>
            {
                //客户端接收信息
                string mes = Encoding.UTF8.GetString(byteBlock.Buffer, 0, byteBlock.Len);



                var json = JsonHelper.ServerRequest_deserialization(mes);
                string sid = json[0][0];
                string tab = json[1][0];
                string ret = json[2][0];
                string[] arr = json[3];
                switch (tab)
                {
                    case "uinf":

                        MessageBox.Show(ret, sid);
                        //label4.Text = "你当前的UID:" + arr[0];
                        uid = arr[0];
                        break;
                    case "sc":

                        switch (ret)
                        {
                            case "mu":
                                Hashtable ht = new Hashtable();
                                List<string> fin = new List<string>();
                                List<string> cin = new List<string>();
                                Dictionary<string, double> dic = new Dictionary<string, double>(new MyDictionaryComparer());
                                ///title
								foreach (var item in arr)
                                {
                                    double sim = Sim(item.Split('|')[0], textBox2.InputText);
                                    if (sim != 0)
                                    {
                                        dic.Add(item, sim);
                                    }
                                }

                                foreach (var item in DictonarySort(dic))
                                {
                                    fin.Add(item);

                                }
                                dic.Clear();
                                ///artists
                                ///
                                foreach (var item in arr)
                                {
                                    double sim = Sim(item.Split('|')[1], textBox2.InputText);
                                    if (sim != 0)
                                    {
                                        dic.Add(item, sim);
                                    }
                                }
                                foreach (var item in DictonarySort(dic))
                                {
                                    if (!fin.Exists(t => t == item))
                                        fin.Add(item);
                                }


                                ///artists
                                ///
                                foreach (var item in arr)
                                {
                                    double sim = Sim(item.Split('|')[2], textBox2.InputText);
                                    if (sim != 0)
                                    {
                                        dic.Add(item, sim);
                                    }
                                }
                                foreach (var item in DictonarySort(dic))
                                {
                                    if (!fin.Exists(t => t == item))
                                        fin.Add(item);
                                }
                                addElement(fin.ToArray());



                                break;

                            default:
                                break;
                        }
                        break;
                    default:
                        break;
                }

                //   MessageBox.Show()
            };

            //声明配置
            var config = new TcpClientConfig();
            config.RemoteIPHost = new IPHost(IP+":"+P1);//远程IPHost
            config.BytePool = BytePool.Default;//设置内存池实例。
            config.BufferLength = 1024 * 64;//缓存池容量
            config.BytePoolMaxSize = 512 * 1024 * 1024;//单个线程内存池容量
            config.BytePoolMaxBlockSize = 20 * 1024 * 1024;//单个线程内存块限制
            config.Logger = new Log();//日志记录器，可以自行实现ILog接口。
            config.SeparateThreadReceive = false;//独立线程接收，当为true时可能会发生内存池暴涨的情况
            config.DataHandlingAdapter = new NormalDataHandlingAdapter();//设置数据处理适配器
            config.OnlySend = false;//仅发送，即不开启接收线程，同时不会感知断开操作。
            config.SeparateThreadSend = false;//在异步发送时，使用独立线程发送
            config.SeparateThreadSendBufferLength = 1024 * 1024;// 独立线程发送缓存区长度。

            //载入配置
            tcpClient.Setup(config);


            try
            {
                //连接
                //执行无异常即连接成功
                tcpClient.Connect();
            }
            catch(Exception e)
            {
                Log(e.Message.ToString());
                //连接异常
            }
        }
        private List<string> DictonarySort(Dictionary<string, double> dic)
        {

            List<string> di = new List<string>();
            var dicSort = from objDic in dic orderby objDic.Value descending select objDic;
            foreach (KeyValuePair<string, double> kvp in dicSort)
            {
                di.Add(kvp.Key);
            }
            return di;
            //  Response.Write(kvp.Key + "：" + kvp.Value + "<br />");
        }
        public double Sim(string txt1, string txt2)
        {
            List<char> sl1 = txt1.ToCharArray().ToList();
            List<char> sl2 = txt2.ToCharArray().ToList();
            //去重
            List<char> sl = sl1.Union(sl2).ToList<char>();

            //获取重复次数
            List<int> arrA = new List<int>();
            List<int> arrB = new List<int>();
            foreach (var str in sl)
            {
                arrA.Add(sl1.Where(x => x == str).Count());
                arrB.Add(sl2.Where(x => x == str).Count());
            }
            //计算商
            double num = 0;
            //被除数
            double numA = 0;
            double numB = 0;
            for (int i = 0; i < sl.Count; i++)
            {
                num += arrA[i] * arrB[i];
                numA += Math.Pow(arrA[i], 2);
                numB += Math.Pow(arrB[i], 2);
            }
            double cos = num / (Math.Sqrt(numA) * Math.Sqrt(numB));
            Random rt = new Random();

            return cos;
        }

		private void ucBtnImg4_BtnClick(object sender, EventArgs e)
		{
            //listBox1.Items.Clear();
            search();
        }
        void search()
        {
            if (tcpClient.Online)

            {
                var json = JsonHelper.ClientRequest_serialization(uid, "sc", "mu", textBox2.InputText);
                tcpClient.Send(Encoding.UTF8.GetBytes(json));
            }
        }

		private void ucDataGridView1_ItemClick(object sender, DataGridViewEventArgs e)
		{
			if(e.CellControl!=null)
                MessageBox.Show(e.CellIndex.ToString()+"."+ e.RowIndex.ToString());
		}

		void loadDemo()
		{
            for (int i = 0; i < 30; i++)
            {
                var item = new ListViewItem(new[] { "搁浅" + i.ToString(), "周杰伦" + i.ToString(), "七里香" + i.ToString() });
                item.BackColor = Color.White;
                this.materialListView1.Items.Add(item);


            }
        }

		private void materialListView1_ItemChecked(object sender, ItemCheckedEventArgs e)
		{
            var temp = e.Item;
		}

		private void materialListView1_ItemCheck(object sender, ItemCheckEventArgs e)
		{
            var temp = e.Index;
        }

		private void materialListView1_SelectedIndexChanged(object sender, EventArgs e)
		{
            
		}
        string getID()
        {
            return "error";
        }
        void play(string filename)
        {
            
            if (this.currentMusic== filename)
            {
                wplayer.controls.stop();
                wplayer.controls.play();
                return;
            }



            //  wplayer.currentPlaylist.a
            /* if (!listBox2.Items.Contains(listBox1.SelectedItem))
             {
                 listBox2.Items.Add(listBox1.SelectedItem);
             }
             listBox2.SelectedItem = listBox1.SelectedItem;*/
            /*

                playList.Add(new string[] { temp[0], temp[1], temp[2], temp[3], temp[4] });
                //歌曲名//歌手//专辑//ID//类型
                var cell = new ListViewItem(new[] { temp[0], temp[1], temp[2] });

                this.materialListView1.Items.Add(cell);*/
            
            Log(setPlay(filename));
        }
        string setPlay(string title)
        {

            try
            {
                currentMusic = title;
                
                if (File.Exists(path + @"/" + title))
                {
                    //本地已缓存，直接播放本地缓存

                    pictureBox1.Image = Client.Properties.Resources.已缓存;
                    wplayer.URL = path + @"/" + title;
                    wplayer.controls.play();

                    return "播放成功";
                }
                else
                {
                    pictureBox1.Image = Client.Properties.Resources.未缓存;

                    //本地无缓存，需要先下载

                    if (BeginDownload(title))
                    {


                        return "下载中";
                    }
                    else
                    {

                        return "下载失败";
                    }
                }
            }






            catch (Exception e)
            {

                Log(e.Message.ToString());
                return "播放失败" + e.Message;
            }
            
        }

        private bool BeginDownload(string mid)
        {
            if (fileClient != null && fileClient.Online)
            {
                if (string.IsNullOrEmpty(mid))
                {
                    Log("Url不能为空");
                    return false;
                }

                try
                {
                    TransferFlags transferFlags = new TransferFlags();
                    transferFlags = transferFlags | TransferFlags.BreakpointResume;
                    transferFlags = transferFlags | TransferFlags.QuickTransfer;


                    UrlFileInfo urlFileInfo = UrlFileInfo.CreateDownload(mid, transferFlags);

                    fileClient.RequestTransfer(urlFileInfo);

                    return true;
                }
                catch (Exception e)
                {
                    Log(e.Message);

                    return false;
                }
            }
            else
            {
                Log("未连接");

                return false;
            }
        }

		private void ucBtnImg8_BtnClick(object sender, EventArgs e)
		{
        }

		private void ucBtnImg6_BtnClick(object sender, EventArgs e)
		{
            if (materialListView2.Visible)
            {
                materialListView2.Visible = false;
                return;
            }
            materialListView2.Visible = true;
            materialListView2.Items.Clear();
            foreach (var cell in playList)
			{

                var item = new ListViewItem(new string[] { cell[0], cell[1], cell[2] });
                this.materialListView2.Items.Add(item);
            }
        }

		private void timer1_Tick(object sender, EventArgs e)
		{
            switch (wplayer.playState)
            {
                case WMPLib.WMPPlayState.wmppsPlaying:

                    var EndPoint = wplayer.currentMedia.duration;
                    if (EndPoint == 0)
                        return;
                    ucTrackBar1.MaxValue = (int)wplayer.currentMedia.duration;

                    ucTrackBar1.Value = (int)wplayer.controls.currentPosition;
                    label1.Text = wplayer.currentMedia.durationString;
                    label2.Text = wplayer.controls.currentPositionString;
                    break;

                default:
                    break;
            }
        }

		private void materialListView2_SelectedIndexChanged(object sender, EventArgs e)
		{

		}

		private void materialListView1_MouseDoubleClick(object sender, MouseEventArgs e)
		{
            if (materialListView1.SelectedItems != null)
            {
                foreach (ListViewItem item in materialListView1.SelectedItems)
                {
                    var filename = musicList[item.Index];

                    play(filename[3] + "." + filename[4]);
                    if (IndexOf(playList,new string[] { filename[0], filename[1], filename[2], filename[3], filename[4] }) == -1)
                    {
                        playList.Add(new string[] { filename[0], filename[1], filename[2], filename[3], filename[4] });
                        currentTitle = new string[] { filename[0], filename[1], filename[2], filename[3], filename[4] };

                    }
                }

            }
        }

		private void ucBtnImg1_BtnClick(object sender, EventArgs e)
		{
            switch (wplayer.playState)
            {
                case WMPPlayState.wmppsUndefined://未知状态
                    ucBtnImg1.Image = Resources.play;
                    break;
                case WMPPlayState.wmppsStopped://播放停止
                    ucBtnImg1.Image = Resources.play;
                    break;
                case WMPPlayState.wmppsPaused://播放暂停
                    ucBtnImg1.Image = Resources.play;
                    wplayer.controls.play();
                    break;
                case WMPPlayState.wmppsPlaying://正在播放
                    ucBtnImg1.Image = Resources.pause;
                    wplayer.controls.pause();
                    break;
                default:
                    break;
            }
        }

		private void ucBtnImg3_BtnClick(object sender, EventArgs e)
		{
            int index = IndexOf(playList,currentTitle);

            if (index == playList.Count - 1)
            {
                wplayer.URL = path + @"/" + playList[0][3] + "." + playList[0][4];
                currentTitle = new string[] { playList[0][0], playList[0][1], playList[0][2], playList[0][3], playList[0][4] };
                wplayer.controls.play();
            }
            else 
            {

                wplayer.URL = path + @"/" + playList[index+1][3] + "." + playList[index + 1][4];
                currentTitle = new string[] { playList[index + 1][0], playList[index + 1][1], playList[index + 1][2], playList[index + 1][3], playList[index + 1][4] };
                wplayer.controls.play();
            }
		}int IndexOf(List<string[]> list, string[] array)
        {
            int index = 0;
			foreach (var item in list)
			{
                if (Equals(item, array))
                    return index;
                index++;
			}
            return -1;
        }


        public bool Equals(string[] list1,string[] list2)
		{
            if (list1.Length!= list2.Length)
                return false;
            for (int i = 0; i < list1.Length; i++)
                if (list1[i] != list2[i])
                    return false;
            return true;
        }

		// override object.GetHashCode
		public override int GetHashCode()
		{
			// TODO: write your implementation of GetHashCode() here
			throw new NotImplementedException();
			return base.GetHashCode();
		}

		private void materialListView2_DoubleClick(object sender, EventArgs e)
		{

		}

		private void ucBtnImg2_BtnClick(object sender, EventArgs e)
		{
            int index = IndexOf(playList, currentTitle);

            if (index == 0)
            {
                wplayer.URL = path + @"/" + playList[playList.Count - 1][3] + "." + playList[playList.Count - 1][4];
                currentTitle = new string[] { playList[playList.Count - 1][0], playList[playList.Count - 1][1], playList[playList.Count - 1][2], playList[playList.Count - 1][3], playList[playList.Count - 1][4] };
                wplayer.controls.play();
            }
            else
            {

                wplayer.URL = path + @"/" + playList[index - 1][3] + "." + playList[index - 1][4];
                currentTitle = new string[] { playList[index - 1][0], playList[index - 1][1], playList[index - 1][2], playList[index - 1][3], playList[index - 1][4] };
                wplayer.controls.play();
            }
        }

		private void ucTrackBar1_ValueChanged(object sender, EventArgs e)
		{
            
		}

		private void ucTrackBar1_MouseUp(object sender, MouseEventArgs e)
		{
            wplayer.controls.currentPosition = ucTrackBar1.Value;
        }

		void addElement(string[] list)
        {

            this.materialListView1.Items.Clear();
            musicList = new List<string[]>();
            foreach (var item in list)
            {
                var temp = item.Split('|');
                musicList.Add(new string[] {temp[0], temp[1], temp[2], temp[3], temp[4]});
                //歌曲名//歌手//歌手//ID//类型
                  var cell = new ListViewItem(new[] { temp[0], temp[1], temp[2] });
                
                this.materialListView1.Items.Add(cell);
            }
        }


        private void ucDataGridView1_Load(object sender, EventArgs e)
		{

		}

		private void ucBtnImg5_BtnClick(object sender, EventArgs e)
		{
			Setting form2 = new Setting();

			form2.ShowDialog();
		}
	}
}
